-
Notifications
You must be signed in to change notification settings - Fork 891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GODRIVER-3156 Detect and discard closed idle connections. #1815
GODRIVER-3156 Detect and discard closed idle connections. #1815
Conversation
// If the connection has been idle for less than 10 seconds, skip the liveness | ||
// check. | ||
idleStart, ok := c.idleStart.Load().(time.Time) | ||
if !ok || idleStart.Add(10*time.Second).After(time.Now()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the significance of 10 seconds?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My reference was the PyMongo driver, which checks connection liveness when it's idle for >1 second. I wanted to mitigate the risk that checking liveness too often would cause performance problems (since a liveness check takes at least 1ms), so I increased that threshold to 10s.
This looks relevant: |
API Change ReportNo changes found! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I recommend adding a unit test for isAlive:
func TestConnection_IsAlive(t *testing.T) {
t.Run("idle time lt 10 seconds", func(t *testing.T) {
mockConn := &drivertest.ChannelNetConn{}
conn := &connection{
nc: mockConn,
}
conn.idleStart.Store(time.Now())
assert.True(t, conn.isAlive())
})
t.Run("idle time gt 10 seconds", func(t *testing.T) {
mockConn := &drivertest.ChannelNetConn{
ReadResp: make(chan []byte, 1),
}
mockConn.ReadResp <- []byte{5, 0, 0, 0, 0}
conn := &connection{
nc: mockConn,
}
conn.idleStart.Store(time.Now().Add(-11 * time.Second))
assert.False(t, conn.isAlive())
})
t.Run("read error", func(t *testing.T) {
mockConn := &drivertest.ChannelNetConn{
ReadErr: make(chan error, 1),
}
mockConn.ReadErr <- errors.New("")
conn := &connection{
nc: mockConn,
}
conn.idleStart.Store(time.Now().Add(-11 * time.Second))
assert.False(t, conn.isAlive())
})
// TODO:
// case: deadline exceeded
}
drivers-pr-bot please backport to release/1.17 |
Co-authored-by: Steven Silvester <[email protected]> (cherry picked from commit 6952473)
…lease/1.17] (#1841) Co-authored-by: Matt Dale <[email protected]>
Co-authored-by: Steven Silvester <[email protected]>
…ster] (#1842) Co-authored-by: Steven Silvester <[email protected]>
GODRIVER-3156
Summary
connection.idleDeadline
toconnection.idleStart
, allowing us to calculate different idle deadlines for different purposes.Background & Motivation
Currently the Go driver never attempts to detect connections that were closed by the other side when checking out connections. As a result, it's possible to return a connection that's been closed by the other side where any read or write operations will immediately fail. Instead, we should check if the connection has been closed when checking out a connection.